#include "simpleftpwidget.h"
#include "config.h"

#ifdef Q_OS_LINUX
#include "dbusutil.h"
#endif

#include "dropeater.h"
#include "qurl.h"
#include "ui_simpleftpwidget.h"

#include <QBuffer>
#include <QDesktopServices>
#include <QFileInfo>
#include <QMessageBox>
#include <QProcess>
#include <QTemporaryFile>
#include <dragentereater.h>
#include <eventutil.h>

#include <QDir>
#include <QMenu>
#include <QTextCodec>

#include <dialog/contentdialog.h>
SimpleFtpWidget::SimpleFtpWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SimpleFtpWidget)
    , ftp(nullptr)
    , m_get_type(Download)
{
    ui->setupUi(this);

    ui->treeWidget->setHeaderLabels(QStringList()
                                    << tr("Name")
                                    << tr("Size")
                                    << tr("Owner")
                                    << tr("Group")
                                    << tr("Time"));
    ui->btn_up->setIcon(QPixmap(":/images/images/cdtoparent.png"));

    ui->progressBar->setMaximum(100);

    connect(ui->treeWidget, &QTreeWidget::itemActivated,this, &SimpleFtpWidget::slot_itemActivated);

    tmpfile = new QTemporaryFile(this);

    setAcceptDrops(true);
    new DragEnterEater([this](QDropEvent *event){
        event->accept();
        return true;
    }, this);


    // FTP 文件拖入时上传文件
    new DropEater([this](QDropEvent *event){
        auto filepath = EventUtil::getDropOneFileName(event);
        if (filepath.isEmpty() == false) {
            if (ftp) {
                QMessageBox::information(this, "发现文件", tr("%1").arg(filepath));
                auto file = new QFile(filepath);
                file->open(QIODevice::ReadOnly);
                QFileInfo fileinfo(filepath);
                if (m_ftpPath.isEmpty()) {
                    ftp->put(file, QString::fromLatin1(fileinfo.fileName().toLocal8Bit()));
                } else {
                    QString path = m_ftpPath + QDir::separator() + QString::fromLatin1(fileinfo.fileName().toLocal8Bit());
                    ftp->put(file, path.toUtf8());
                }
            }
        }
        return false;
    }, this);
}

SimpleFtpWidget::~SimpleFtpWidget()
{
    delete ui;
}

void SimpleFtpWidget::slot_itemActivated(QTreeWidgetItem *item, int column)
{
    QString name = item->text(0);

    qd << "choose:" << name << m_latin1FileMap.value(name);

    //
    QString latin1_name = m_latin1FileMap.value(name);

    if (m_isDirectory.value(name)) { // Enter Directory
        ui->treeWidget->clear();
        m_isDirectory.clear();
        m_latin1FileMap.clear();
        m_ftpPath += '/';
//        m_ftpPath += name;
        m_ftpPath += latin1_name;

        qd << "cd:" << name <<  m_latin1FileMap.value(name);
        qd << "cd:" << name << m_ftpPath;
        ftp->cd(m_ftpPath);
        ftp->list();
    } else { // Download File

        QString fileName = ui->treeWidget->currentItem()->text(0);
//        tmpfile = new QTemporaryFile;
//        m_temporary[fileName] = tmpfile;

        qd << "获取文件:" << fileName;
//        tmpfile->setFileName(fileName);
        qd << "tmpfile->open():" << tmpfile->open() << tmpfile->fileName();

//        tmpfile->open(QIODevice::WriteOnly);

        if (m_get_type == Download)
            if (QMessageBox::question(this, "确认下载文件?", "是否下载此文件?") & QMessageBox::Yes) {
                ftp->get(fileName, tmpfile);
                //            emit onFtpOpen(fileName, )
            } else {

            }
        else
            ftp->get(fileName, tmpfile);
    }
}

void SimpleFtpWidget::slot_commandFinished(int commandId, bool error)
{
    qd << "slot_commandFinished" << error;
    if (ftp->currentCommand() == QFtp::ConnectToHost) {
        qd << "QFtp::ConnectToHost";
        if (error) {
            auto err = ftp->errorString();
            QMessageBox::critical(this, "QFtp::ConnectToHost", ftp->errorString());

            on_btn_connect_clicked();
            ui->status->setText(err);
            return;
        }
    }

    if (ftp->currentCommand() == QFtp::Login) {
        qd << "QFtp::Login" << error;
        ftp->list();
    }

    if (ftp->currentCommand() == QFtp::Cd) {
        qd << "QFtp::Cd" << error;
        if (error) {
            qd << ftp->errorString();
            QMessageBox::critical(this, "QFtp::Cd", ftp->errorString());
        }
    }

    if (ftp->currentCommand() == QFtp::Get) {
        qd << "QFtp::Get" << error;

        if (error) { // Canceled
            qd << ftp->errorString();
            QMessageBox::critical(this, "QFtp::Get", ftp->errorString());
            tmpfile->close();
            tmpfile->remove();
        } else { // finished
            tmpfile->close();

            if (m_get_type == Download)
            if (QMessageBox::question(this, "下载完成", "是否打开目录?") & QMessageBox::StandardButton::Yes) {
            #if defined (Q_OS_WIN32)
                QProcess process;
                process.startDetached(QString("explorer /select,\"%1\"").arg(tmpfile->fileName().replace("/", "\\")));//启动后分离，即非阻塞
            #elif defined (Q_OS_LINUX)
                DBusUtil::showFileLocation(tmpfile->fileName());
            #endif
            } else {} // wrap
            else {
                ContentDialog dialog;
                QFile file(tmpfile->fileName());
                file.open(QIODevice::ReadOnly);
                dialog.setText(file.readAll());
                dialog.exec();
            }
        }
    }
    if (ftp->currentCommand() == QFtp::List) {
        qd << "QFtp::List" << error;
        if (error) {
            qd << ftp->errorString();
            QMessageBox::critical(this, "QFtp::List", ftp->errorString());
        } else {
            if (m_isDirectory.isEmpty()) {
                ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(QStringList() << "<无文件>"));
                ui->treeWidget->setEnabled(false);
            }
        }
    }

    if (ftp->currentCommand() == QFtp::Put) {
        qd << "QFtp::Put" << error;
        if (error) { // Cancel
            qd << ftp->errorString();
            QMessageBox::critical(this, "QFtp::Put", ftp->errorString());
        } else { // Finished
            ui->treeWidget->clear();
            m_isDirectory.clear();
            m_latin1FileMap.clear();
            ftp->list();
        }
    }
}

void SimpleFtpWidget::slot_listInfo(const QUrlInfo &urlInfo)
{
    qd << "slot_listInfo";
    QTreeWidgetItem *item = new QTreeWidgetItem;

    qd << urlInfo.name();

    item->setText(0, urlInfo.name().toLatin1());
    item->setText(1, QString::number(urlInfo.size()));
    item->setText(2, urlInfo.owner());
    item->setText(3, urlInfo.group());
    item->setText(4, urlInfo.lastModified().toString("yyyy-MM-dd"));

    item->setIcon(0, QPixmap(urlInfo.isDir() ? ":/images/images/dir.png" : ":/images/images/file.png"));

    m_isDirectory[urlInfo.name().toLatin1()] = urlInfo.isDir();
    m_latin1FileMap[urlInfo.name().toLatin1()] = urlInfo.name();
    ui->treeWidget->addTopLevelItem(item);
    if (ui->treeWidget->currentItem() == nullptr) {
        ui->treeWidget->setCurrentItem(ui->treeWidget->topLevelItem(0));
        ui->treeWidget->setEnabled(true);
    }

    ui->btn_up->setEnabled(true);
}

void SimpleFtpWidget::slot_dataTransferProgress(qint64 readBytes, qint64 totalBytes)
{
    ui->progressBar->setValue(100.0 * (double(readBytes) / double(totalBytes)));
    ui->status->setText(tr("dataTransfer: %1/%2 bytes.").arg(readBytes).arg(totalBytes));
}

QString SimpleFtpWidget::toSpecial(const QString &input)
{

#ifdef Q_OS_WIN
    return QString::fromLatin1(input.toLocal8Bit());
#else
    QTextCodec *codec= QTextCodec::codecForName("gbk");
    if (codec)
    {
        return QString::fromLatin1(codec->fromUnicode(input));
    }
    else
    {
        return QString("");
    }
#endif
}

QString SimpleFtpWidget::fromSpecial(const QString &input)
{
    return QString();
}

void SimpleFtpWidget::on_btn_up_clicked()
{
    if (ftp) {
        ui->treeWidget->clear();
        m_isDirectory.clear();
        m_latin1FileMap.clear();
        m_ftpPath = m_ftpPath.left(m_ftpPath.lastIndexOf("/"));
        if (m_ftpPath.isEmpty()) {
            ui->btn_up->setEnabled(false);
            ftp->cd("/");
        } else {
            ftp->cd(m_ftpPath);
        }
        ftp->list();

        ui->status->setText(tr("Cd '%1' .").arg(m_ftpPath));
    }
}

void SimpleFtpWidget::connectToFtp()
{
    ftp = new QFtp(this);
    connect(ftp, &QFtp::commandFinished,this, &SimpleFtpWidget::slot_commandFinished);
    connect(ftp, &QFtp::listInfo,this, &SimpleFtpWidget::slot_listInfo);
    connect(ftp, &QFtp::dataTransferProgress,this, &SimpleFtpWidget::slot_dataTransferProgress);

    ui->treeWidget->clear();
    m_ftpPath.clear();
    m_isDirectory.clear();
    m_latin1FileMap.clear();

    ui->treeWidget->clear();
    ui->btn_connect->setText("Disconnect");

    QString ftpUrl =  this->ui->edit_ftp->text();
    // ftp->connectToHost(url);

    QUrl url(ftpUrl);
    if (url.isValid() == false // no prefix 'ftp://'
        || url.scheme().toLower() != QLatin1String("ftp")) {
        ftp->connectToHost(ftpUrl, 21);
        ftp->login();
        qd << "login: default";
    } else {
        int port = 21;
        if (url.port() != -1) {
            port = url.port();
        }
        ftp->connectToHost(url.host(), port);
        qd << "connectToHost: " << url.host() << port;

        // ftp://user:pass@...
        if (url.userName().isEmpty() == false) {
            ftp->login(QUrl::fromPercentEncoding(url.userName().toUtf8()), url.password());
            qd << "login: " << QUrl::fromPercentEncoding(url.userName().toUtf8()) << url.password();
        } else {
            // anonymous
            ftp->login();
            qd << "login: anonymous";
        }

        // ftp://user:pass@.../a/b/c
        if (url.path().isEmpty() == false)
            ftp->cd(url.path());
    }

    ui->status->setText(tr("Connecting to FTP server %1...").arg(url.url()));
}

void SimpleFtpWidget::on_btn_connect_clicked()
{
    if (ftp) {
        ftp->abort();
        ftp->deleteLater();
        ftp = nullptr;

        ui->treeWidget->clear();
        // ui->treeWidget->setEnabled(false);
        ui->btn_up->setEnabled(false);
        ui->btn_connect->setEnabled(true);
        ui->btn_connect->setText("Connect");

        ui->status->setText("Please enter the name of an FTP server.");
        return;
    }

    connectToFtp();
}


void SimpleFtpWidget::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
    auto current = ui->treeWidget->currentItem();
    if (current == nullptr) return;

    QMenu menu;
    menu.addAction("查看内容", [this,current](){
        m_get_type = Content;
        slot_itemActivated(current,0);
    });
    menu.addAction("下载", [this,current](){
        m_get_type = Download;
        slot_itemActivated(current,0);
    });

    menu.exec(QCursor::pos());
}

